package command

import (
	"bufio"
	"fmt"
	"net"
	"os"
	"os/user"
	"path/filepath"
	"strings"

	"atomgit.com/openlinksaas/gitwrap/utils"
	"github.com/spf13/cobra"
	"golang.org/x/crypto/ssh"
	"golang.org/x/crypto/ssh/knownhosts"
)

var TestSshCmd = &cobra.Command{
	Use: "testSsh",
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 2 {
			utils.OutputError(fmt.Errorf("need param [host] [ssh key]"))
			return
		}

		sshAddr := args[0]
		sshKeyFile := args[1]

		sshKey, err := os.ReadFile(sshKeyFile)
		if err != nil {
			utils.OutputError(err)
			return
		}
		signer, err := ssh.ParsePrivateKey(sshKey)
		if err != nil {
			utils.OutputError(err)
			return
		}

		client, err := ssh.Dial("tcp", sshAddr, &ssh.ClientConfig{
			User: "git",
			Auth: []ssh.AuthMethod{
				ssh.PublicKeys(signer),
			},
			HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
				line := knownhosts.Line([]string{hostname}, key)
				return fixKnownHosts(line)
			},
		})
		if err != nil {
			utils.OutputError(err)
			return
		}
		defer client.Close()
	},
}

func fixKnownHosts(line string) error {
	line = strings.Trim(line, "\r\n\t ")
	curUser, err := user.Current()
	if err != nil {
		return err
	}
	sshDirPath := filepath.Join(curUser.HomeDir, ".ssh")
	os.Mkdir(sshDirPath, 0700) //skip error check

	hostsPath := filepath.Join(curUser.HomeDir, ".ssh", "known_hosts")
	exist := false
	_, err = os.Stat(hostsPath)
	if err == nil {
		f, err := os.Open(hostsPath)
		if err != nil {
			return err
		}
		defer f.Close()
		r := bufio.NewReader(f)
		for {
			tmpLine, err := r.ReadString('\n')
			tmpLine = strings.Trim(tmpLine, "\r\n\t ")
			if line == tmpLine {
				exist = true
			}
			if err != nil {
				break
			}
		}
	}
	if exist {
		return nil
	}
	//更新 known_hosts 文件
	f, err := os.OpenFile(hostsPath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0600)
	if err != nil {
		return err
	}
	defer f.Close()
	f.WriteString("\n") //skip error check
	f.WriteString(line) //skip error check
	return nil
}
